'''
An override for Python Time Module

@author: Hatem Oraby
'''

from twistedSim.overrideManager import OverrideManager
import time

class SimTime():
    '''
    A module for handling overridden time.
    '''
    def __init__(self):
        #See if time module was overridden yet.
        fn = OverrideManager.getEntity("time.time")
        if fn is not None: #Not yet overridden
            self.time = fn()
        else:
            self.time = time.time()

    def getTime(self):
        '''Return the current saved time '''
        return self.time


    def setTime(self, time):
        '''Set the time'''
        self.time = time
        
    def localtime(self, _secs = None):
        #Though that Python documentation acknowledges that the localtime()
        # function takes an optional argument named secs, however when the
        # keyword secs is passed to the function it raises an error:
        # "TypeError: localtime() takes no keyword arguments"
        #Therefore we don't use here the original secs keyword 
        # but rather use  _secs instead.
        '''Override for time.loacltime() '''
        if _secs == None:
            _secs = SimTimeSingleton.getTime() 
        fn = OverrideManager.getEntity("time.localtime")
        return fn(_secs)

    def gmtime(self, _secs = None):
        '''Override for time.gmtime()'''
        if _secs == None:
            _secs = SimTimeSingleton.getTime() 
        fn = OverrideManager.getEntity("time.gmtime")
        return fn(_secs)

    def asctime(self, _t = None):
        '''Override for time.asctime()'''
        if _t == None:
            _t = SimTimeSingleton.localtime() 
        fn = OverrideManager.getEntity("time.asctime")
        return fn(_t)

    def strftime(self, format, _t = None):
        '''Override for time.strftime()'''
        if _t == None:
            _t = SimTimeSingleton.localtime()
        fn = OverrideManager.getEntity("time.strftime")
        return fn(format, _t)

    def ctime(self, _secs = None):
        '''Override for time.ctime()'''
        if _secs == None:
            _secs = SimTimeSingleton.getTime()
        fn = OverrideManager.getEntity("time.ctime")
        return fn(_secs)

class SimTimeSingleton():
    ''' 
    A singleton for L{SimTime}
    ''' 
    SimTimeInstance = SimTime()

    def getTime(self):
        return SimTimeSingleton.SimTimeInstance.getTime()
    getTime = classmethod(getTime)
    
    def setTime(self, time):
        return SimTimeSingleton.SimTimeInstance.setTime(time)
    setTime = classmethod(setTime)

    def localtime(self, _secs = None): 
        return SimTimeSingleton.SimTimeInstance.localtime(_secs = _secs)
    localtime = classmethod(localtime)

    def gmtime(self, _secs = None):
        return SimTimeSingleton.SimTimeInstance.gmtime(_secs = _secs)
    gmtime = classmethod(gmtime)

    def asctime(self, _t = None):
        return SimTimeSingleton.SimTimeInstance.asctime(_t = _t)
    asctime = classmethod(asctime)

    def strftime(self, format, _t = None):
        return SimTimeSingleton.SimTimeInstance.strftime(format, _t = _t)
    strftime = classmethod(strftime)

    def ctime(self, _secs = None):
        return SimTimeSingleton.SimTimeInstance.ctime(_secs = _secs)
    ctime = classmethod(ctime)
SimTimeSingleton = SimTime()


    

def installModule():
    '''Installs time overriding module '''
    import time
    OverrideManager.storeEntity(originalFn = time.time,
                                fullName = "time.time")
    time.time = SimTimeSingleton.getTime
    
    OverrideManager.storeEntity(originalFn = time.asctime,
                                fullName = "time.asctime")
    time.asctime = SimTimeSingleton.asctime
    
    OverrideManager.storeEntity(originalFn = time.localtime,
                                fullName = "time.localtime")
    time.localtime = SimTimeSingleton.localtime
    
    OverrideManager.storeEntity(originalFn = time.gmtime,
                                fullName = "time.gmtime")
    time.gmtime = SimTimeSingleton.gmtime
    
    OverrideManager.storeEntity(originalFn = time.strftime,
                                fullName = "time.strftime")
    time.strftime = SimTimeSingleton.strftime
    
    OverrideManager.storeEntity(originalFn = time.ctime,
                                fullName = "time.ctime")
    time.ctime = SimTimeSingleton.ctime